]> dgit.raspbian.org Git - gnome-shell.git/commitdiff
appDisplay: Refactor page switching on overshoot
authorJonas Dreßler <verdre@v0yd.nl>
Fri, 9 Dec 2022 22:39:10 +0000 (23:39 +0100)
committerMarge Bot <marge-bot@gnome.org>
Mon, 19 Dec 2022 11:37:58 +0000 (11:37 +0000)
Right now we have a behavior in the appGrid where "bumping" the cursor
against the monitor edge during DND switches the page immediately, and
holding it there (at the monitor edge) switches pages again after a timeout.

With the next commit we'll introduce another way of switching pages during
DND, that is hovering over the next/prev page indicator to switch pages. To
allow those two methods to play well together, refactor the "overshoot" page
switching to make the timeout into a more generic "repeat" timeout. This
means we can now divide page switching can be roughly divided into two
different steps:

- Switch page immediately when bumping cursor against screen edge, also
works when repeatedly "bumping"

- Switch page automatically again after a second when keeping the cursor at
the screen edge without moving

We'll reuse the "repeat" timeout that's introduced here in the next commit,
where we'll introduce page switching by hovering the next/prev indicators.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2581>

js/ui/appDisplay.js

index 3fa1451d09300c77be28b904753da482fff1a50a..8c75f0473545675eb7af736d39dd07fb228b4edd 100644 (file)
@@ -43,8 +43,8 @@ const PAGE_PREVIEW_ANIMATION_TIME = 150;
 const PAGE_INDICATOR_FADE_TIME = 200;
 const PAGE_PREVIEW_RATIO = 0.20;
 
-const OVERSHOOT_THRESHOLD = 20;
-const OVERSHOOT_TIMEOUT = 1000;
+const DRAG_PAGE_SWITCH_IMMEDIATELY_THRESHOLD_PX = 20;
+const DRAG_PAGE_SWITCH_REPEAT_TIMEOUT = 1000;
 
 const DELAYED_MOVE_TIMEOUT = 200;
 
@@ -638,8 +638,7 @@ var BaseAppView = GObject.registerClass({
             () => this._redisplay(), this);
 
         // Drag n' Drop
-        this._lastOvershoot = -1;
-        this._lastOvershootTimeoutId = 0;
+        this._lastOvershootCoord = -1;
         this._delayedMoveData = null;
 
         this._dragBeginId = 0;
@@ -839,64 +838,72 @@ var BaseAppView = GObject.registerClass({
         this._delayedMoveData = null;
     }
 
-    _resetOvershoot() {
-        if (this._lastOvershootTimeoutId)
-            GLib.source_remove(this._lastOvershootTimeoutId);
-        this._lastOvershootTimeoutId = 0;
-        this._lastOvershoot = -1;
+    _resetDragPageSwitchRepeat() {
+        if (this._dragPageSwitchRepeatTimeoutId) {
+            GLib.source_remove(this._dragPageSwitchRepeatTimeoutId);
+            delete this._dragPageSwitchRepeatTimeoutId;
+        }
+
+        this._lastOvershootCoord = -1;
+    }
+
+    _setupDragPageSwitchRepeat(direction) {
+        if (this._dragPageSwitchRepeatTimeoutId)
+            GLib.source_remove(this._dragPageSwitchRepeatTimeoutId);
+
+        this._dragPageSwitchRepeatTimeoutId =
+            GLib.timeout_add(GLib.PRIORITY_DEFAULT, DRAG_PAGE_SWITCH_REPEAT_TIMEOUT, () => {
+                this.goToPage(this._grid.currentPage + direction);
+
+                return GLib.SOURCE_CONTINUE;
+            });
+        GLib.Source.set_name_by_id(this._dragPageSwitchRepeatTimeoutId,
+            '[gnome-shell] this._dragPageSwitchRepeatTimeoutId');
     }
 
-    _handleDragOvershoot(dragEvent) {
+    _dragMaybeSwitchPageImmediately(dragEvent) {
+        // Already animating
+        if (this._adjustment.get_transition('value') !== null)
+            return;
+
         const [gridX, gridY] = this.get_transformed_position();
         const [gridWidth, gridHeight] = this.get_transformed_size();
 
         const vertical = this._orientation === Clutter.Orientation.VERTICAL;
-        const gridStart = vertical ?
-            ? gridY + DRAG_OVERSHOOT_THRESHOLD
-            : gridX + DRAG_OVERSHOOT_THRESHOLD;
+        const gridStart = vertical
+            ? gridY + DRAG_PAGE_SWITCH_IMMEDIATELY_THRESHOLD_PX
+            : gridX + DRAG_PAGE_SWITCH_IMMEDIATELY_THRESHOLD_PX;
         const gridEnd = vertical
-            ? gridY + gridHeight - OVERSHOOT_THRESHOLD
-            : gridX + gridWidth - OVERSHOOT_THRESHOLD;
+            ? gridY + gridHeight - DRAG_PAGE_SWITCH_IMMEDIATELY_THRESHOLD_PX
+            : gridX + gridWidth - DRAG_PAGE_SWITCH_IMMEDIATELY_THRESHOLD_PX;
 
-        // Already animating
-        if (this._adjustment.get_transition('value') !== null)
-            return;
+        const dragCoord = vertical ? dragEvent.y : dragEvent.x;
+        if (dragCoord > gridStart && dragCoord < gridEnd) {
+            const moveDelta = Math.abs(this._lastOvershootCoord - dragCoord);
 
-        // Within the grid boundaries
-        const dragPosition = vertical ? dragEvent.y : dragEvent.x;
-        if (dragPosition > gridStart && dragPosition < gridEnd) {
-            // Check whether we moved out the area of the last switch
-            if (Math.abs(this._lastOvershoot - dragPosition) > OVERSHOOT_THRESHOLD)
-                this._resetOvershoot();
+            // We moved back out of the overshoot region into the grid. If the
+            // move was sufficiently large, reset the overshoot so that it's
+            // possible to repeatedly bump against the edge and quickly switch
+            // pages.
+            if (this._lastOvershootCoord >= 0 &&
+                moveDelta > DRAG_PAGE_SWITCH_IMMEDIATELY_THRESHOLD_PX)
+                this._resetDragPageSwitchRepeat();
 
             return;
         }
 
-        // Still in the area of the previous page switch
-        if (this._lastOvershoot >= 0)
+        // Still in the area of the previous overshoot
+        if (this._lastOvershootCoord >= 0)
             return;
 
-        const rtl = this.get_text_direction() === Clutter.TextDirection.RTL;
-        if (dragPosition <= gridStart)
-            this.goToPage(this._grid.currentPage + (rtl ? 1 : -1));
-        else if (dragPosition >= gridEnd)
-            this.goToPage(this._grid.currentPage + (rtl ? -1 : 1));
-        else
-            return; // don't go beyond first/last page
-
-        this._lastOvershoot = dragPosition;
+        let direction = dragCoord <= gridStart ? -1 : 1;
+        if (this.get_text_direction() === Clutter.TextDirection.RTL)
+            direction *= -1;
 
-        if (this._lastOvershootTimeoutId > 0)
-            GLib.source_remove(this._lastOvershootTimeoutId);
+        this.goToPage(this._grid.currentPage + direction);
+        this._setupDragPageSwitchRepeat(direction);
 
-        this._lastOvershootTimeoutId =
-            GLib.timeout_add(GLib.PRIORITY_DEFAULT, OVERSHOOT_TIMEOUT, () => {
-                this._resetOvershoot();
-                this._handleDragOvershoot(dragEvent);
-                return GLib.SOURCE_REMOVE;
-            });
-        GLib.Source.set_name_by_id(this._lastOvershootTimeoutId,
-            '[gnome-shell] this._lastOvershootTimeoutId');
+        this._lastOvershootCoord = dragCoord;
     }
 
     _onDragBegin() {
@@ -916,11 +923,8 @@ var BaseAppView = GObject.registerClass({
 
         const appIcon = dragEvent.source;
 
-        // Handle the drag overshoot. When dragging to above the
-        // icon grid, move to the page above; when dragging below,
-        // move to the page below.
         if (appIcon instanceof AppViewItem)
-            this._handleDragOvershoot(dragEvent);
+            this._dragMaybeSwitchPageImmediately(dragEvent);
 
         this._maybeMoveItem(dragEvent);
 
@@ -940,7 +944,8 @@ var BaseAppView = GObject.registerClass({
             this._dragMonitor = null;
         }
 
-        this._resetOvershoot();
+        this._resetDragPageSwitchRepeat();
+
         this._appGridLayout.hidePageIndicators();
         this._swipeTracker.enabled = true;
     }